package jmind.core.mongodb;

import java.util.*;

import jmind.base.util.DateUtil;
import jmind.base.util.DataUtil;

import org.bson.types.ObjectId;
import org.springframework.util.CollectionUtils;

import com.google.common.base.Function;
import com.google.common.collect.Lists;
import com.mongodb.BasicDBObject;
import com.mongodb.BasicDBObjectBuilder;
import com.mongodb.DBObject;

/**
 * 帮助工具
 * @author weibo.xie
 * 2011-12-1
 */
public class MongodbTool {
    /**
     * 按DBObject filed 排序
     * 2014-1-13 
     * @param res
     * @param val
     * @return
     */
    public static List<DBObject> sort(List<DBObject> res, final String val) {
        Collections.sort(res, new Comparator<DBObject>() {
            @Override
            public int compare(DBObject p1, DBObject p2) {
                Integer count1 = (Integer) p1.get(val);
                Integer count2 = (Integer) p2.get(val);
                return count2.compareTo(count1);
            }
        });
        return res;
    }

    public static List<ObjectId> toObjectIdList(List<String> fids) {
        return Lists.transform(fids, new Function<String, ObjectId>() {
            @Override
            public ObjectId apply(String input) {
                return new ObjectId(input);
            }
        });
    }

    public static List<ObjectId> toObjectIdList(String[] fids) {
        List<ObjectId> fid = new ArrayList<ObjectId>();
        for (String id : fids) {
            fid.add(new ObjectId(id));
        }
        return fid;
    }

    /**
     * 提取某列的值
     * @param list
     * @param key
     * @return
     */
    @SuppressWarnings("unchecked")
    public final static <T> List<T> toIdList(List<DBObject> list, String key) {
        if (CollectionUtils.isEmpty(list)) {
            return Collections.emptyList();
        }
        List<T> newList = new ArrayList<T>(list.size());
        for (DBObject obj : list) {
            newList.add((T) obj.get(key));
        }
        return newList;
    }

    public final static DBObject getOneDay(String date) {
        Date start = DateUtil.parse(date, DateUtil.DEFAULT_PATTERN);
        Date end = DateUtil.add(start, Calendar.DATE, 1);
        DBObject query = new BasicDBObject("$gte", new ObjectId(start)).append("$lt", new ObjectId(end));
        return BasicDBObjectBuilder.start(MongoCollection.ID, query).get();
    }

    /**
     * 解析两个日期之间
     * 2013-10-9 
     * @param >=startDate
     * @param < endDate
     * @return
     */
    public final static DBObject getDays(String startDate, String endDate) {
        Date start = DateUtil.parse(startDate, DateUtil.DEFAULT_PATTERN);
        Date end = DateUtil.parse(endDate, DateUtil.DEFAULT_PATTERN);
        DBObject query = new BasicDBObject("$gte", new ObjectId(start)).append("$lt", new ObjectId(end));
        return BasicDBObjectBuilder.start(MongoCollection.ID, query).get();
    }

    public final static ObjectId getOidByDate(String date) {
        Date start = DateUtil.parse(date, DateUtil.DEFAULT_PATTERN);
        return new ObjectId(start);
    }

    /**
     * 把ObjectId 格式化为  yyyyMMdd 的日期字符串
     * @param oid
     * @return
     */
    public final static String parseOid(ObjectId oid, String formart) {
        if (DataUtil.isEmpty(formart)) {
            return DateUtil.format(oid.getTime());
        }
        return DateUtil.format(new Date(oid.getTime()), formart);
    }

    /**
     * 将2个BasicDBObject 中Number 属性合并
     * @param source 源
     * @param obj
     * @return
     */
    public static BasicDBObject add(BasicDBObject source, BasicDBObject obj) {
        for (String field : obj.keySet()) {
            Object val = obj.get(field);
            if (val instanceof BasicDBObject) {
                if (!source.containsField(field)) {
                    source.put(field, new BasicDBObject());
                }

                add((BasicDBObject) source.get(field), (BasicDBObject) val);
            } else if (val instanceof Number) {
                int c = ((Number) val).intValue();
                if (source.containsField(field)) {
                    source.put(field, source.getInt(field) + c);
                } else {
                    source.put(field, c);
                }
            }
        }
        return source;
    }

    /**
     * 把DBObject 的list ,根据某个键值,转成map
     * @param list
     * @param key
     * @return
     */
    public Map<Object, DBObject> toMap(List<DBObject> list, String key) {
        Map<Object, DBObject> map = new HashMap<Object, DBObject>();
        for (DBObject jo : list) {
            Object k = jo.removeField(key);
            map.put(k, jo);
        }
        return map;
    }

}
